#include "System.h"

#include "MessageProcessor.h"

#include <iostream>
#include <SDL_syswm.h>
#include <SDL.h>

System::System( int screen_width, int screen_height ) :
    m_Quit(0)
{
    m_Width = screen_width;
    m_Height = screen_height;
    init(screen_width, screen_height);
    MessageProcessor::GetInstance().SetSystem(this);
    MessageProcessor::GetInstance().SetSystemMessages(&m_Messages);
}

System::~System()
{
    destroy();
}

void print_SDL_error()
{
	std::cout << SDL_GetError() << std::endl;
}

void System::HandleEvents ()
{
    SDL_GetMouseState (&m_CurrentMousePosition.X, &m_CurrentMousePosition.Y);

    SystemMessage systMess;
    m_Messages.clear();

	SDL_Event sdl_event;
    while( SDL_PollEvent( &sdl_event ) ) {
		if( sdl_event.type == SDL_QUIT ) {
            m_Quit = true;
        }
		switch (sdl_event.type)
		{
            case SDL_KEYDOWN:
                switch (sdl_event.key.keysym.sym) {
                    case SDLK_a:
                        systMess.Set(smKEY_A_PRESSED, sdl_event.button.x, sdl_event.button.y);
                        m_Messages.push_back(systMess);
                        break;
                    case SDLK_b:
                        systMess.Set(smKEY_B_PRESSED, sdl_event.button.x, sdl_event.button.y);
                        m_Messages.push_back(systMess);
                        break;
                    case SDLK_q:
                        systMess.Set(smKEY_Q_PRESSED, sdl_event.button.x, sdl_event.button.y);
                        m_Messages.push_back(systMess);
                        break;
                    default:
                        break;
                }
                break;
            case SDL_KEYUP:
                switch (sdl_event.key.keysym.sym) {
                    case SDLK_a:
                        systMess.Set(smKEY_A_RELEASED, sdl_event.button.x, sdl_event.button.y);
                        m_Messages.push_back(systMess);
                        break;
                    case SDLK_b:
                        systMess.Set(smKEY_B_RELEASED, sdl_event.button.x, sdl_event.button.y);
                        m_Messages.push_back(systMess);
                        break;
                    case SDLK_q:
                        systMess.Set(smKEY_Q_RELEASED, sdl_event.button.x, sdl_event.button.y);
                        m_Messages.push_back(systMess);
                        break;
                    default:
                        break;
                }
                break;

            case SDL_MOUSEMOTION:
             //   printf("Mouse moved by %d,%d to (%d,%d)\n",
             //          sdl_event.motion.xrel, sdl_event.motion.yrel,
              //         sdl_event.motion.x, sdl_event.motion.y);
                systMess.Set(smMOUSE_MOVED, sdl_event.button.x, sdl_event.button.y);
                m_Messages.push_back(systMess);
                break;
            case SDL_MOUSEBUTTONDOWN:
				switch( sdl_event.button.button ) {
					case SDL_BUTTON_LEFT:
                        systMess.Set(smLEFT_MB_PRESS, sdl_event.button.x, sdl_event.button.y);
                        m_Messages.push_back(systMess);
						break;
					case SDL_BUTTON_RIGHT:
                        systMess.Set(smRIGHT_MB_PRESS, sdl_event.button.x, sdl_event.button.y);
                        m_Messages.push_back(systMess);
						break;
					default:
						break;
				}
             //   printf( "Mouse button %d pressed at (%d,%d)\n", sdl_event.button.button, sdl_event.button.x, sdl_event.button.y );
                break;
			case SDL_MOUSEBUTTONUP:
				switch( sdl_event.button.button ) {
					case SDL_BUTTON_LEFT:
                        systMess.Set(smLEFT_MB_RELEASE, sdl_event.button.x, sdl_event.button.y);
                        m_Messages.push_back(systMess);
						break;
					case SDL_BUTTON_RIGHT:
						break;
					default:
						break;
				}
				break;
        }
	}
}
/*
SystemMessages& System::GetMessages()
{
    return m_Messages;
}
*/
void System::UpdateScreen()
{
	//SDL_GL_SwapBuffers();
}

bool System::IsQuit()
{
	return m_Quit;
}

void System::init( int screen_width, int screen_height )
{
    SDL_Surface* videoSurface = NULL;
	if( SDL_Init( SDL_INIT_EVERYTHING ) == -1 ) {
		std::cout << "error loading SDL_init" << std::endl;
		print_SDL_error();
    }

    // todo remove this shit
    freopen( "CON", "w", stdout );
    freopen( "CON", "w", stderr );


	// SDL_HWSURFACE : Create the video surface in video memory
	// SDL_DOUBLEBUF : Enable hardware double buffering; only valid with SDL_HWSURFACE
	// SDL_OPENGL: Create an OpenGL rendering context. You should have previously set OpenGL video attributes with SDL_GL_SetAttribute.
    videoSurface = SDL_SetVideoMode( screen_width, screen_height, 32, SDL_HWSURFACE | SDL_GL_DOUBLEBUFFER );
	if (videoSurface != NULL) {
		SDL_WM_SetCaption( "DirectX", NULL );
	}
	else {
		std::cerr << "Video initialization failed " << std::endl;
		print_SDL_error();
	}
}

HWND System::GetWindowHandle()
{
    SDL_SysWMinfo SysInfo;
    SDL_VERSION(&SysInfo.version);

    if(SDL_GetWMInfo(&SysInfo) <= 0) {
        printf("%s : %d\n", SDL_GetError(), (int)SysInfo.window);
        return NULL;
    }
    return SysInfo.window;
}

SystemMessages& System::GetMessages()
{
    return m_Messages;
}

void System::destroy()
{
//	m_Messages.clear();
	SDL_Quit();
}

int System::GetWidth()
{
    return m_Width;
}

int System::GetHeight()
{
    return m_Height;
}
